package com.situ.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.situ.domain.dto.AddRoleDTO;
import com.situ.domain.dto.RoleAndMenuDTO;
import com.situ.domain.dto.RolePageQueryDTO;
import com.situ.domain.dto.UpdateRoleDTO;
import com.situ.domain.entity.RoleMenu;
import com.situ.domain.entity.TRole;
import com.situ.domain.vo.BasePageQueryVO;
import com.situ.domain.vo.RoleAndMenuVO;
import com.situ.mapper.TRoleMapper;
import com.situ.service.RoleMenuService;
import com.situ.service.RoleService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@RequiredArgsConstructor
public class RoleServiceImpl extends ServiceImpl<TRoleMapper, TRole> implements RoleService {

    private final RoleMenuService roleMenuService;

    private final TRoleMapper roleMapper;

    /**
     * 分页查询角色列表
     * @param pageQueryDTO
     * @return
     */
    @Override
    public BasePageQueryVO<TRole> getRoleList(RolePageQueryDTO pageQueryDTO) {
        Page<TRole> page = Page.of(pageQueryDTO.getCurrentPage(),pageQueryDTO.getPageSize());
        this.lambdaQuery()
                .like(StrUtil.isNotBlank(pageQueryDTO.getQueryString()),TRole::getRolename,pageQueryDTO.getQueryString())
                .page( page);
        BasePageQueryVO<TRole> pageQueryVO = BasePageQueryVO.<TRole>builder()
                .currentPage(page.getCurrent())
                .pageSize(page.getSize())
                .pageTotal(page.getTotal())
                .pages(page.getPages())
                .list(page.getRecords())
                .build();
        return pageQueryVO;
    }

    /**
     * 添加角色
     * @param roleDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addRole(AddRoleDTO roleDTO) {
        TRole role = new TRole();
        BeanUtil.copyProperties(roleDTO,role);
        role.setStatus(1);
        this.save(role);
        saveRolAndMenu(roleDTO, role);
    }

    /**
     * 保存角色和菜单关系
     * @param roleDTO
     * @param role
     */
    private void saveRolAndMenu(AddRoleDTO roleDTO, TRole role) {
        List<RoleMenu> list = roleDTO.getMenuIds()
                .stream()
                .map(menuId -> RoleMenu
                        .builder()
                        .roleFk(role.getRoleid())
                        .menuFk(menuId)
                        .build())
                .toList();
        roleMenuService.saveBatch(list);
    }


    /**
     * 锁定或解锁角色
     * @param status
     * @param id
     */
    @Override
    public void lock(Integer status, Long id) {
        this.lambdaUpdate()
                .eq(TRole::getRoleid, id)
                .set(TRole::getStatus, status)
                .update();
    }


    /**
     * 根据角色id查询角色信息
     * @param id
     * @return
     */
    @Override
    public RoleAndMenuVO getRoleAndMenuById(Long id) {
        RoleAndMenuDTO roleAndMenuDTO = roleMapper.getRoleAndMenuById(id);
        RoleAndMenuVO roleAndMenuVO = new RoleAndMenuVO();
        BeanUtil.copyProperties(roleAndMenuDTO,roleAndMenuVO);
        if (roleAndMenuDTO.getMenuList() == null || roleAndMenuDTO.getMenuList().isEmpty()){
            roleAndMenuVO.setMenuIds(List.of());
        }else {
            List<Long> menuIds = roleAndMenuDTO.getMenuList()
                    .stream()
                    .map(menu -> Long.valueOf(menu.getId()))
                    .toList();
            roleAndMenuVO.setMenuIds(menuIds);
        }
        return roleAndMenuVO;
    }


    /**
     * 修改角色
     * @param roleDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRole(UpdateRoleDTO roleDTO) {
        // 删除原有的角色和菜单关系
        roleMenuService.lambdaUpdate()
                .eq(RoleMenu::getRoleFk, roleDTO.getRoleid())
                .remove();
        TRole tRole = new TRole();
        BeanUtil.copyProperties(roleDTO,tRole);
        this.saveOrUpdate(tRole);
        saveRolAndMenu(roleDTO, tRole);
    }
}
